#include "StdAfx.h"
#include <GL/glu.h>
#include "FontGlyph.h"
#include <float.h>
#include "DoTriangle.h"

namespace tge
{

#ifndef CALLBACK
#define CALLBACK
#endif

	static CPolygonTess * s_pTess = NULL;

	GePoint2d CFontGlyph::s_lastPt;
	GePoint2d CFontGlyph::s_bezier[3];

	int CFontGlyph::s_nAppendCount = 0;
	int CFontGlyph::s_nBezierCount = 0;


	CFontGlyph::CFontGlyph(void)
	{
	}

	CFontGlyph::~CFontGlyph(void)
	{
	}

	void CFontGlyph::MoveTo(const GePoint2d &pt)
	{
		m_arrPoly.Add(pt);
		s_nAppendCount++;
		s_lastPt = pt;
	}
	CFontGlyph*CFontGlyph::CreateNewObj()
	{
		return new CFontGlyph();
	}

	void CFontGlyph::LineTo(const GePoint2d &pt)
	{
		m_arrPoly.Add(pt);
		s_nAppendCount++;
		s_lastPt = pt;
	}

	UINT CFontGlyph::GetPolygonCount()const
	{
		int nCount = m_arrCount.GetSize();
		// 	m_arrPolyPointer.RemoveAll();
		// 	GePoint2d * p = m_arrPoly.GetData();
		// 	for(int i = 0; i < nCount; i++){
		// 		m_arrPolyPointer.Add(p);
		// 		p += m_arrCount[i];
		// 	}

		return nCount;
	}
	void CFontGlyph::CreatePolygons()
	{
		int nCount = m_arrCount.GetSize();
		m_arrPolyPointer.RemoveAll();
		GePoint2d * p = m_arrPoly.GetData();
		for (int i = 0; i < nCount; i++){
			m_arrPolyPointer.Add(p);
			p += m_arrCount[i];
		}
	}
	UINT CFontGlyph::GetPolygon(UINT nIndex, const GePoint2d ** ppPoly)const
	{
		*ppPoly = m_arrPolyPointer[nIndex];
		return m_arrCount[nIndex];
	}

	void CFontGlyph::CloseFigure()
	{
		m_arrCount.Add(s_nAppendCount);
		s_nAppendCount = 0;
	}


	void CFontGlyph::GetTess(triangle_data&data)const
	{
		if (!m_arrTriangle.size()){

			GePoint2dArray vts;
			DoTriangle::Begin(m_arrPoly.GetCount() * 2, GLU_TESS_WINDING_NONZERO);

			int nCount = GetPolygonCount();
			for (int i = 0; i < nCount; i++){
				const GePoint2d * pf;
				int nPointCount = GetPolygon(i, &pf);
				GePoint2dArray arr;
				arr.resize(nPointCount);
				for (int j = 0; j < nPointCount; j++){
					arr[j] = pf[j];
				}
				DoTriangle::AddContour(arr);
			}
			int numVts;
			DoTriangle_vertex*vts2;
			int numIdx;
			long*idx;
			DoTriangle::End(numVts, vts2, numIdx, idx);
			data.m_numVts = numVts;
			data.m_arrVts = new GePoint2d[numVts];
			for (int i = 0; i < numVts; ++i)
			{
				data.m_arrVts[i] = vts2[i].pt;
			}
			data.m_numTri = numIdx / 3;
			data.m_arrIdx = new long[numIdx];
			memcpy(data.m_arrIdx, idx, sizeof(long)*numIdx);
		}
	}

	double CFontGlyph::GetWidth()
	{
		return m_gmf.gmfBlackBoxX;
	}

	GLYPHMETRICSFLOAT * CFontGlyph::GetMetrics()
	{
		return &m_gmf;
	}

	triangle_data::triangle_data()
	{
		memset(this, 0, sizeof(triangle_data));
	}

	triangle_data& triangle_data::operator=(const triangle_data&data)
	{
		delete[] m_arrVts;
		delete[] m_arrIdx;
		m_numVts = data.m_numVts;
		m_arrVts = new GePoint2d[m_numVts];
		memcpy(m_arrVts, data.m_arrVts, sizeof(GePoint2d)*m_numVts);
		m_numTri = data.m_numTri;
		m_arrIdx = new long[3 * m_numTri];
		memcpy(m_arrIdx, data.m_arrIdx, sizeof(long)*m_numTri * 3);
		return *this;
	}

	triangle_data::~triangle_data()
	{
		delete[] m_arrVts;
		delete[] m_arrIdx;
	}
	triangle_data&triangle_data::operator+=(const triangle_data&td)
	{
		GePoint2d*vts = new GePoint2d[m_numVts + td.m_numVts];
		memcpy(vts, m_arrVts, sizeof(GePoint2d)*m_numVts);
		memcpy(&vts[m_numVts], td.m_arrVts, sizeof(GePoint2d)*td.m_numVts);
		delete[] m_arrVts;
		m_arrVts = vts;
		long*idx = new long[m_numTri * 3 + td.m_numTri * 3];
		memcpy(idx, m_arrIdx, sizeof(long)*m_numTri * 3);
		int num = td.m_numTri * 3;
		int i0 = m_numTri * 3;
		for (int i = 0; i < num; ++i)
		{
			idx[i0 + i] = td.m_arrIdx[i] + m_numVts;
		}
		m_numVts += td.m_numVts;
		delete[] m_arrIdx;
		m_arrIdx = idx;
		m_numTri += td.m_numTri;
		return *this;
	}
}